﻿Imports System
Imports System.Runtime.CompilerServices
Imports System.Threading

Namespace System.Workflow.Runtime.DebugEngine
    Friend MustInherit Class BreakSafeBase([Of] T As { ICloneable, New })
        ' Methods
        Protected Sub New(ByVal controllerManagedThreadId As Integer)
            Me.currentData = If((CType(Nothing, T) Is Nothing), Activator.CreateInstance([Of] T), CType(Nothing, T))
            Me.nonEEDataClone = CType(Nothing, T)
            Me.nonEEDataConsistent = False
            Me.nonEEIgnoreUpdate = False
            Me.nonEELock = New Mutex(False)
            Me.controllerManagedThreadId = controllerManagedThreadId
        End Sub

        Protected Function GetControllerUpdateObject() As Object
            Return Me.controllerUpdateObject
        End Function

        Protected Function GetReaderData() As T
            Return DirectCast(Me.currentData, T)
        End Function

        Protected Function GetWriterData() As T
            If Me.IsEECall Then
                If (Me.nonEEDataConsistent AndAlso Not Me.nonEEIgnoreUpdate) Then
                    Return DirectCast(Me.currentData, T)
                End If
                Me.nonEEIgnoreUpdate = True
                Dim local As T = DirectCast(Me.currentData, T)
                Return DirectCast(local.Clone, T)
            End If
            Me.nonEEIgnoreUpdate = False
            Dim currentData As T = DirectCast(Me.currentData, T)
            Return DirectCast(currentData.Clone, T)
        End Function

        Protected Sub Lock()
            If Not Me.IsEECall Then
                Me.nonEELock.WaitOne
            End If
        End Sub

        Protected Sub SaveData(ByVal data As T)
            If Me.IsEECall Then
                Me.currentData = data
            Else
                Me.nonEEDataClone = data
                Me.nonEEDataConsistent = True
                Me.controllerUpdateObject = Nothing
                If Not Me.nonEEIgnoreUpdate Then
                    Me.currentData = data
                End If
                Me.nonEEDataConsistent = False
                Me.nonEEDataClone = CType(Nothing, T)
            End If
        End Sub

        Protected Sub SetControllerUpdateObject(ByVal updateObject As Object)
            Me.controllerUpdateObject = updateObject
        End Sub

        Protected Sub Unlock()
            If Not Me.IsEECall Then
                Me.nonEELock.ReleaseMutex
            End If
        End Sub


        ' Properties
        Private ReadOnly Property IsEECall As Boolean
            Get
                Return (Thread.CurrentThread.ManagedThreadId = Me.controllerManagedThreadId)
            End Get
        End Property


        ' Fields
        Private controllerManagedThreadId As Integer
        Private controllerUpdateObject As Object
        Private currentData As Object ModReq(IsVolatile)
        Private nonEEDataClone As T
        Private nonEEDataConsistent As Boolean ModReq(IsVolatile)
        Private nonEEIgnoreUpdate As Boolean ModReq(IsVolatile)
        Private nonEELock As Mutex
    End Class
End Namespace

